

class TC1_PrivateUndefined
{
public:
	TC1_PrivateUndefined() {}
private:
	TC1_PrivateUndefined(const TC1_PrivateUndefined&);
	TC1_PrivateUndefined& operator=(const TC1_PrivateUndefined&);
};

class TC1_DeletedFunction
{
public:
	TC1_DeletedFunction() {}

	//By conventiion, deleted functions are declared public. 
	TC1_DeletedFunction(const TC1_DeletedFunction&) = delete;
	TC1_DeletedFunction& operator=(const TC1_DeletedFunction&) = delete;
};

void tc1_SameInMostCases()
{
	TC1_PrivateUndefined tc1_pu1;	
	// TC1_PrivateUndefined tc1_pu2(tc1_pu1);

	TC1_DeletedFunction tc1_df1;
	//TC1_DeletedFunction tc1_df2(tc1_df1);
}

void TC2_OnlyAcceptInt(int v) {}
void TC2_OnlyAcceptInt(double) = delete;
void TC2_OnlyAcceptInt(bool) = delete;

void tc2_DeletedFunctionsCanBeAnyFunction()
{
	TC2_OnlyAcceptInt(1);
	//	TC2_OnlyAcceptInt(true);	//function is deleted
	//	TC2_OnlyAcceptInt(1.1);		//function is deleted
}

template<typename T>
void TC2_processPointer(T* ptr) {}

template<>
void TC2_processPointer<void>(void* ptr) = delete;

void tc3_PreventTemplateInstantiations()
{
	int* iPtr = 0;
	TC2_processPointer(iPtr);

	//void* vPtr = 0;
	//TC2_processPointer(vPtr);		//error, function is deleted.
}

class TC4_Widget
{
public:
	template<typename T>
	void processPointer(T* ptr){}
};

template<>
void TC4_Widget::processPointer<void>(void*) = delete;

void tc4_DeleteTemplatedMemberFunction()
{
	int* iPtr = 0;
	TC4_Widget widget;
	widget.processPointer(iPtr);

	//void* vPtr = 0;
	//widget.processPointer(vPtr);
}


int Test_I11_PreferDeletedFunctionsToPrivateUndefinedOnes(int, char**)
{
	tc1_SameInMostCases();
	tc2_DeletedFunctionsCanBeAnyFunction();
	tc3_PreventTemplateInstantiations();
	tc4_DeleteTemplatedMemberFunction();

	return 0;
}

/*
Things to Remember
- Prefer deleted functions to private undefined ones.
- Any function may be deleted, including non-member functions and template
  instantiations.
*/